#include "DXDevice.h"
#include "DXDeviceWP8.h"
#include "Screen.h"
using namespace DirectX;
//DXDevice* DXDevice::instance;
void DXDevice::Init(void* params[])
{
	if(instance == nullptr)
	{
		instance = new DXDeviceWP8(params);
		instance->InitSpecificDevice();
		instance->InitMatrixStack();
		instance->m_MatrixProjection.SetIdentity();
		instance->m_MatrixView.SetIdentity();
		instance->vsActived = NULL;
		instance->psActived = NULL;
		if(DXDevice::GetInstance()->GetDeviceContext() && DXDevice::GetInstance()->GetDeviceType() != DeviceType::DEVICE_WP8_XAML)
		{
			
		}
		instance->PushRenderTarget(instance->renderTargetMain);
		//-------------------------------------------------
		D3D11_DEPTH_STENCIL_DESC dsDesc;

		// Depth test parameters
		dsDesc.DepthEnable = true;
		dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
		dsDesc.DepthFunc = D3D11_COMPARISON_LESS;

		// Stencil test parameters
		dsDesc.StencilEnable = true;
		dsDesc.StencilReadMask = 0xFF;
		dsDesc.StencilWriteMask = 0xFF;

		// Stencil operations if pixel is front-facing
		dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
		dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
		dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
		dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

		// Stencil operations if pixel is back-facing
		dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
		dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
		dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
		dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

		instance->depthStencilDescCurrent = dsDesc;
		// Create depth stencil state
		instance->GetD3D11Device()->CreateDepthStencilState(&(instance->depthStencilDescCurrent), &(instance->pDepthStencilStateCurrent));
		if(DXDevice::GetInstance()->GetDeviceContext())
		{
			instance->GetDeviceContext()->OMSetDepthStencilState(instance->pDepthStencilStateCurrent, 1);
		}
		//-------------------------------------
		ZeroMemory(&(instance->blendStateDescCurrent), sizeof(D3D11_BLEND_DESC1));
		instance->blendStateDescCurrent.RenderTarget[0].BlendEnable = FALSE;
		instance->blendStateDescCurrent.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
		instance->blendStateDescCurrent.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
		instance->blendStateDescCurrent.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
		instance->blendStateDescCurrent.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
		instance->blendStateDescCurrent.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
		instance->blendStateDescCurrent.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
		instance->blendStateDescCurrent.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
		instance->GetD3D11Device()->CreateBlendState1(&(instance->blendStateDescCurrent), &(instance->pBlendStateCurrent));
		ZeroMemory(instance->blendFactor, sizeof(float)*4);
		instance->blendSampleMask   = 0xffffffff;
		if(DXDevice::GetInstance()->GetDeviceContext())
		{
			instance->GetDeviceContext()->OMSetBlendState(instance->pBlendStateCurrent, instance->blendFactor, instance->blendSampleMask);
		}
		//-------------------------------------
		instance->m_MatrixProjection2D.SetOrthoCentered((float)instance->GetWidth(), (float)instance->GetHeight(), 0.9f, 1000.0f);
		Screen::Init(instance->GetWidth(), instance->GetHeight());
		instance->m_MatrixProjection2DLogical.SetOrthoCentered(2*Screen::GetInstance()->GetRightLogical(), 2.0f,0.9f,1000.0f);
		instance->isDrawing2D = false;
		//	1-------2
		//			3
		//	4
		//	6-------5
		float rectangleVertices[] = 
		{
			-1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
			1.0f, 1.0f, 1.0f,
			1.0f, -1.0f, 1.0f,
			-1.0f, 1.0f, 1.0f,
			1.0f, -1.0f, 1.0f,
			-1.0f, -1.0f, 1.0f
		};
		D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
		vertexBufferData.pSysMem = rectangleVertices;
		vertexBufferData.SysMemPitch = 0;
		vertexBufferData.SysMemSlicePitch = 0;
		CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(float)*30, D3D11_BIND_VERTEX_BUFFER);
		vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
		vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

		instance->GetD3D11Device()->CreateBuffer(
				&vertexBufferDesc,
				&vertexBufferData,
				&(instance->m_vertexBuffer2D)
				);
		//------------------------------------
		D3D11_QUERY_DESC qd;
		ZeroMemory(&qd, sizeof(qd));
		qd.Query = D3D11_QUERY_EVENT;
		HRESULT hr = instance->GetD3D11Device()->CreateQuery(&qd, &instance->queryEvent);
		if( FAILED( hr ) )
		{
		}
		instance->bCommandCheckingStarted = false;
	}
}
void DXDevice::SetProjectionPerspectiveMatrix(float angleFovy, float ratio, float fNear, float fFar)
{
	//XMMATRIX mp  = XMMatrixPerspectiveFovLH(angleFovy,float(GetWidth())/float(GetHeight()),fNear,fFar);
	//XMStoreFloat4x4(&m_MatrixProjection, mp);
	m_MatrixProjection.SetPerspectiveFovy(angleFovy, ratio, fNear, fFar);
}
void DXDevice::SetProjectionOrthoMatrix(float left, float right, float bottom, float top, float zNear, float zFar) //zNear must not equal 0.0f
{
	//XMMATRIX mp = XMMatrixOrthographicLH(GetWidth(),GetHeight(),fNear,fFar); //D3DXMatrixOrthoOffCenterLH 
	//XMStoreFloat4x4(&m_MatrixProjection, mp);
	m_MatrixProjection.SetOrtho(left,right,bottom,top,zNear,zFar);
}
void DXDevice::SetProjectionMatrix(Matrix  &matrix)
{
	m_MatrixProjection = matrix;
}
void DXDevice::SetViewMatrix(float xEye, float yEye, float zEye, float xDes
		, float yDes, float zDes, float xUp, float yUp, float zUp)
{
	/*
	XMVECTOR eye = XMVectorSet( xEye, yEye, zEye, 0.0);
	XMVECTOR des = XMVectorSet( xDes, yDes, zDes, 0.0);
	XMVECTOR up = XMVectorSet( xUp, yUp, zUp, 0.0);
	XMMATRIX mv = XMMatrixLookAtLH(eye, des, up);
	XMStoreFloat4x4(&m_MatrixView, mv);
	*/
	m_MatrixView.SetView(xEye, yEye, zEye, xDes
		, yDes, zDes, xUp, yUp, zUp);
}
void DXDevice::SetViewMatrix(Matrix  &matrix)
{
	m_MatrixView = matrix;
}
void DXDevice::SetViewport(float x, float y, float width, float height)
{
	CD3D11_VIEWPORT viewport(x, y, width, height);
	m_d3dContext->RSSetViewports(1, &viewport);
}
void DXDevice::InitMatrixStack()
{
	Matrix identityM;
	identityM.SetIdentity();
	m_MatrixStack.push_back(identityM);
}
void DXDevice::PushMatrix()
{
	Matrix matrix;
	if(m_MatrixStack.size() > 0)
	{
		matrix = m_MatrixStack.back();
	}
	else
	{
		matrix.SetIdentity();
	}
	m_MatrixStack.push_back(matrix);
}
void DXDevice::PopMatrix()
{
	if(m_MatrixStack.size() > 1)
	{
		m_MatrixStack.pop_back();
	}
}
void DXDevice::SetIdentityMatrix()
{
	m_MatrixStack.back().SetIdentity();
}
void DXDevice::Transform(const Matrix &matrix)
{
	m_MatrixStack.back() = m_MatrixStack.back()*matrix;
}
void DXDevice::TransformLocal(const Matrix &matrix)
{
	m_MatrixStack.back() = matrix*m_MatrixStack.back();
}
void DXDevice::Translate(float x, float y, float z)
{
	Matrix trans;
	trans.SetTranslate(x, y, z);
	m_MatrixStack.back() = m_MatrixStack.back()*trans;
}
void DXDevice::Scale(float x, float y, float z)
{
	Matrix scale;
	scale.SetScale(x, y, z);
	m_MatrixStack.back() = m_MatrixStack.back()*scale;
}
void DXDevice::RotateOy(float radian)
{
	Matrix rotate;
	rotate.SetRotateOy(radian);
	m_MatrixStack.back() = m_MatrixStack.back()*rotate;
}
void DXDevice::RotateOz(float radian)
{
	Matrix rotate;
	rotate.SetRotateOz(radian);
	m_MatrixStack.back() = m_MatrixStack.back()*rotate;
}
void DXDevice::RotateOz(float radian, float x, float y)
{
	Matrix trans;
	trans.SetTranslate(x, y, 0.0);
	Matrix itrans;
	itrans.SetTranslate(-x, -y, 0.0);
	Matrix rotate;
	rotate.SetRotateOz(radian);
	m_MatrixStack.back() = m_MatrixStack.back()*itrans*rotate*trans;
}
void DXDevice::RotateAxis(float radian, float x, float y, float z)
{
	Matrix rotate;
	rotate.SetRotateAxis(radian, x, y, z);
	m_MatrixStack.back() = m_MatrixStack.back()*rotate;
}
Matrix  DXDevice::GetMatrixWorldViewProjection()
{
	Matrix  wvp = m_MatrixStack.back()*m_MatrixView*m_MatrixProjection;
	return wvp;
}
void DXDevice::SetActiveVertexShader(VertexShader* vs)
{
	vsActived = vs;
	m_d3dContext->VSSetShader(
	vs->dxVS,
	nullptr,
	0
	);
}
void DXDevice::SetActivePixelShader(PixelShader* ps)
{
	psActived = ps;
	m_d3dContext->PSSetShader(
	ps->dxPS,
	nullptr,
	0
	);
}
void DXDevice::SetActiveMaterial(Material* m)
{
	materialActived = m;
	SetActiveVertexShader(m->vs);
	SetActivePixelShader(m->ps);
}
/*
bool DXDevice::SetCurrentVertexShaderUniformBufferData(int start, int count, void* data)
{
	if(GetActiveVertexShader())
	{
		return GetActiveVertexShader()->SetUniformBufferData(start, count, data);
	}
	return false;
}
bool DXDevice::SetCurrentPixelShaderUniformBufferData(int start, int count, void* data)
{
	if(GetActivePixelShader())
	{
		return GetActivePixelShader()->SetUniformBufferData(start, count, data);
	}
	return false;
}
*/
void DXDevice::Draw(D3D_PRIMITIVE_TOPOLOGY primitiveType, UINT startIndex, UINT count)
{
	DXDevice::GetInstance()->GetDeviceContext()->IASetPrimitiveTopology(primitiveType);
	DXDevice::GetInstance()->GetDeviceContext()->IASetInputLayout(GetActiveVertexShader()->GetInputLayout());

	GetActiveVertexShader()->PushShaderUniformBuffer();
	DXDevice::GetInstance()->GetDeviceContext()->Draw(count, startIndex);
}
void DXDevice::BeginDraw2D()
{
	if(isDrawing2D == false)
	{
		m_MatrixProjectionStore = m_MatrixProjection;
		m_MatrixProjection = m_MatrixProjection2D;
		SetDepthTest(false);
		isDrawing2D = true;
	}
}
void DXDevice::EndDraw2D()
{
	if(isDrawing2D)
	{
		m_MatrixProjection = m_MatrixProjectionStore;
		SetDepthTest(true);
		isDrawing2D = false;
	}
}
void DXDevice::Draw2DTextureScreenCoord(Texture* texture, Sampler* sampler, RectScreenF des, RectScreenF source)
{
	float vertexData[] = 
	{
		des.left, des.bottom, 10.0, source.left, source.top,
		des.right, des.bottom, 10.0, source.right, source.top,
		des.right, des.top, 10.0, source.right, source.bottom,
		des.left, des.bottom, 10.0, source.left, source.top,
		des.right, des.top, 10.0, source.right, source.bottom,
		des.left, des.top, 10.0, source.left, source.bottom
	};
	// Lock the vertex buffer.

    D3D11_MAPPED_SUBRESOURCE mappedBuffer;
	GetDeviceContext()->Map(m_vertexBuffer2D, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedBuffer);
	memcpy(mappedBuffer.pData, vertexData, sizeof(float) * 30);
    GetDeviceContext()->Unmap(m_vertexBuffer2D, 0);
	UINT stride = sizeof(float)*5;
	UINT offset = 0;
	GetDeviceContext()->IASetVertexBuffers(
		0,
		1,
		&m_vertexBuffer2D,
		&stride,
		&offset
		);
	Material *material = GetActiveMaterial();
	Matrix model = GetMatrixWorld();
	material->SetUniformVertexByType(SU_MATRIX_WORLD,&model);
	material->SetUniformVertexByType(SU_MATRIX_VIEW,&m_MatrixView);
	material->SetUniformVertexByType(SU_MATRIX_PROJECTION,&m_MatrixProjection);
	material->PushMaterialDataVertex();
	material->PushMaterialDataPixel();
	material->ps->SetTexture(texture, material->ps->textureMap[0].slot);
	material->ps->SetSampler(sampler, material->ps->samplerMap[0].slot);
	Draw(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,0,6);
	/*
	float vertexData[] = 
	{
		des.left, des.bottom, 10.0, source.left, source.top,
		des.right, des.bottom, 10.0, source.right, source.top,
		des.right, des.top, 10.0, source.right, source.bottom,
		des.left, des.bottom, 10.0, source.left, source.top,
		des.right, des.top, 10.0, source.right, source.bottom,
		des.left, des.top, 10.0, source.left, source.bottom
	};
	// Lock the vertex buffer.

    D3D11_MAPPED_SUBRESOURCE mappedBuffer;
	GetDeviceContext()->Map(m_vertexBuffer2D, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedBuffer);
	memcpy(mappedBuffer.pData, vertexData, sizeof(float) * 30);
    GetDeviceContext()->Unmap(m_vertexBuffer2D, 0);
	UINT stride = sizeof(float)*5;
	UINT offset = 0;
	GetDeviceContext()->IASetVertexBuffers(
		0,
		1,
		&m_vertexBuffer2D,
		&stride,
		&offset
		);
	VertexShader* vs = GetActiveVertexShader();
	Matrix model = GetMatrixWorld();
	vs->SetUniformByType(SU_MATRIX_MODEL,&model);
	vs->SetUniformByType(SU_MATRIX_VIEW,&m_MatrixView);
	vs->SetUniformByType(SU_MATRIX_PROJECTION,&m_MatrixProjection);
	D3D11_SAMPLER_DESC samplerDesc;
	samplerDesc.Filter = texture->GetFilter();
	samplerDesc.AddressU = texture->GetWrapMode();
	samplerDesc.AddressV = texture->GetWrapMode();
	samplerDesc.AddressW = texture->GetWrapMode();
	samplerDesc.MipLODBias = 0.0f;
	samplerDesc.MaxAnisotropy = 1;
	samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
	samplerDesc.BorderColor[0] = 0;
	samplerDesc.BorderColor[1] = 0;
	samplerDesc.BorderColor[2] = 0;
	samplerDesc.BorderColor[3] = 0;
	samplerDesc.MinLOD = 0;
	samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
	ID3D11SamplerState* m_sampleState;
	GetD3D11Device()->CreateSamplerState(&samplerDesc, &m_sampleState);
	PixelShader* ps = GetActivePixelShader();
	ps->SetTexture(texture);
	ps->SetSampler(m_sampleState);
	Draw(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,0,6);
	SafeRelease(m_sampleState);
	*/
}
void DXDevice::Draw2DTextureLogicalCoord(Texture* texture, Sampler* sampler, RectScreenF des, RectScreenF source)
{
	float vertexData[] = 
	{
		des.left, des.bottom, 10.0, source.left, source.top,
		des.right, des.bottom, 10.0, source.right, source.top,
		des.right, des.top, 10.0, source.right, source.bottom,
		des.left, des.bottom, 10.0, source.left, source.top,
		des.right, des.top, 10.0, source.right, source.bottom,
		des.left, des.top, 10.0, source.left, source.bottom
	};
	// Lock the vertex buffer.

    D3D11_MAPPED_SUBRESOURCE mappedBuffer;
	GetDeviceContext()->Map(m_vertexBuffer2D, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedBuffer);
	memcpy(mappedBuffer.pData, vertexData, sizeof(float) * 30);
    GetDeviceContext()->Unmap(m_vertexBuffer2D, 0);
	UINT stride = sizeof(float)*5;
	UINT offset = 0;
	GetDeviceContext()->IASetVertexBuffers(
		0,
		1,
		&m_vertexBuffer2D,
		&stride,
		&offset
		);
	Material *material = GetActiveMaterial();
	Matrix model = GetMatrixWorld();
	material->SetUniformVertexByType(SU_MATRIX_WORLD,&model);
	material->SetUniformVertexByType(SU_MATRIX_VIEW,&m_MatrixView);
	material->SetUniformVertexByType(SU_MATRIX_PROJECTION,&m_MatrixProjection2DLogical);
	material->PushMaterialDataVertex();
	material->PushMaterialDataPixel();
	material->ps->SetTexture(texture, material->ps->textureMap[0].slot);
	material->ps->SetSampler(sampler, material->ps->samplerMap[0].slot);
	Draw(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,0,6);
	/*
	float vertexData[] = 
	{
		des.left, des.bottom, 10.0, source.left, source.top,
		des.right, des.bottom, 10.0, source.right, source.top,
		des.right, des.top, 10.0, source.right, source.bottom,
		des.left, des.bottom, 10.0, source.left, source.top,
		des.right, des.top, 10.0, source.right, source.bottom,
		des.left, des.top, 10.0, source.left, source.bottom
	};
	// Lock the vertex buffer.

    D3D11_MAPPED_SUBRESOURCE mappedBuffer;
	GetDeviceContext()->Map(m_vertexBuffer2D, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedBuffer);
	memcpy(mappedBuffer.pData, vertexData, sizeof(float) * 30);
    GetDeviceContext()->Unmap(m_vertexBuffer2D, 0);
	UINT stride = sizeof(float)*5;
	UINT offset = 0;
	GetDeviceContext()->IASetVertexBuffers(
		0,
		1,
		&m_vertexBuffer2D,
		&stride,
		&offset
		);
	VertexShader* vs = GetActiveVertexShader();
	vs->SetUniformByType(SU_MATRIX_MODEL,&(GetMatrixWorld()));
	vs->SetUniformByType(SU_MATRIX_VIEW,&m_MatrixView);
	vs->SetUniformByType(SU_MATRIX_PROJECTION,&m_MatrixProjection2DLogical);
	D3D11_SAMPLER_DESC samplerDesc;
	samplerDesc.Filter = texture->GetFilter();
	samplerDesc.AddressU = texture->GetWrapMode();
	samplerDesc.AddressV = texture->GetWrapMode();
	samplerDesc.AddressW = texture->GetWrapMode();
	samplerDesc.MipLODBias = 0.0f;
	samplerDesc.MaxAnisotropy = 1;
	samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
	samplerDesc.BorderColor[0] = 0;
	samplerDesc.BorderColor[1] = 0;
	samplerDesc.BorderColor[2] = 0;
	samplerDesc.BorderColor[3] = 0;
	samplerDesc.MinLOD = 0;
	samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
	ID3D11SamplerState* m_sampleState;
	GetD3D11Device()->CreateSamplerState(&samplerDesc, &m_sampleState);
	PixelShader* ps = GetActivePixelShader();
	ps->SetTexture(texture);
	ps->SetSampler(m_sampleState);
	Draw(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,0,6);
	SafeRelease(m_sampleState);
	*/
}
void DXDevice::Draw2DTextureFullViewport(Texture* texture, Sampler* sampler)
{
	UINT num = 1;
	D3D11_VIEWPORT viewPort;
	this->m_d3dContext->RSGetViewports(&num, &viewPort);
	RectScreenF rectDes;
	rectDes.FromWidthHeight(-viewPort.Width/2.0,-viewPort.Height/2.0,viewPort.Width,viewPort.Height);
	RectScreenF rectSource;
	rectSource.FromWidthHeight(0,0,1.0,1.0);
	DXDevice::GetInstance()->Draw2DTextureScreenCoord(texture, sampler, rectDes, rectSource);
}
void DXDevice::DrawXColladaDX(XColladaDX* mesh)
{
	for(int i = 0;i<mesh->nodes.size();i++)
	{
		XNode* node = mesh->nodes[i];
		for(int j = 0;j<node->geometries.size();j++)
		{
			PushMatrix();
			XGeometry* geometry = node->geometries[j];
			/*
			if(geometry->vertexPositionBuffer)
			{
				UINT stride = sizeof(float)*3; //Missing stride XCollada
				UINT offset = 0;
				GetDeviceContext()->IASetVertexBuffers(
					0,
					1,
					&(geometry->vertexPositionBuffer),
					&stride,
					&offset
					);
			}
			if(geometry->vertexTexcoordBuffer)
			{
				UINT stride = sizeof(float)*2; //Missing stride XCollada
				UINT offset = 0;
				GetDeviceContext()->IASetVertexBuffers(
					1,
					1,
					&(geometry->vertexTexcoordBuffer),
					&stride,
					&offset
					);
			}
			*/
			ID3D11Buffer* vbs[] = {geometry->vertexPositionBuffer, geometry->vertexTexcoordBuffer};
			unsigned int strides[] = { sizeof(float)*3, sizeof(float)*2 };
			unsigned int offsets [] = { 0, 0 };
			GetDeviceContext()->IASetVertexBuffers(0, 2, vbs, strides, offsets );
			Sampler* s = new Sampler(D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT, D3D11_TEXTURE_ADDRESS_WRAP);
			if(geometry->material)
			{
				SetActiveMaterial(geometry->material);
				TransformLocal(node->transform);
				Matrix model = GetMatrixWorld();
				geometry->material->SetUniformVertexByType(SU_MATRIX_WORLD,&model);
				geometry->material->SetUniformVertexByType(SU_MATRIX_VIEW,&m_MatrixView);
				geometry->material->SetUniformVertexByType(SU_MATRIX_PROJECTION,&m_MatrixProjection);
				geometry->material->PushMaterialDataVertex();
				geometry->material->PushMaterialDataPixel();
				for(std::map<int, Texture*>::iterator it = geometry->material->textureList.begin(); it != geometry->material->textureList.end(); it++)
				{
					geometry->material->ps->SetTexture((*it).second, (*it).first);
					//geometry->material->ps->SetTexture(geometry->material->textureList[0], geometry->material->ps->textureMap[0].slot);
					//geometry->material->ps->SetTexture(TextureManager::GetInstance()->GetTexture("tex1.DDS"), geometry->material->ps->textureMap[0].slot);
				}
				for(std::map<int, Sampler*>::iterator it = geometry->material->samplerState.begin(); it != geometry->material->samplerState.end(); it++)
				{
					geometry->material->ps->SetSampler((*it).second, (*it).first); //temp
				}

			}
			Draw(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,0,geometry->vertexPositionCount);
			SafeDelete(s);
			PopMatrix();
		}
	}
}
void DXDevice::SetDepthTest(BOOL enable)
{
	if(depthStencilDescCurrent.DepthEnable != enable)
	{
		depthStencilDescCurrent.DepthEnable = enable;
		SafeRelease(pDepthStencilStateCurrent);
		GetD3D11Device()->CreateDepthStencilState(&depthStencilDescCurrent, &pDepthStencilStateCurrent);
		GetDeviceContext()->OMSetDepthStencilState(pDepthStencilStateCurrent, 1);
	}
}
void DXDevice::SetStencilTest(BOOL enable)
{
	if(depthStencilDescCurrent.StencilEnable != enable)
	{
		depthStencilDescCurrent.StencilEnable = enable;
		SafeRelease(pDepthStencilStateCurrent);
		GetD3D11Device()->CreateDepthStencilState(&depthStencilDescCurrent, &pDepthStencilStateCurrent);
		GetDeviceContext()->OMSetDepthStencilState(pDepthStencilStateCurrent, 1);
	}
}
void DXDevice::SetBlend(BOOL enable)
{
	if(blendStateDescCurrent.RenderTarget[0].BlendEnable != enable)
	{
		blendStateDescCurrent.RenderTarget[0].BlendEnable = enable;
		SafeRelease(pBlendStateCurrent);
		GetD3D11Device()->CreateBlendState1(&blendStateDescCurrent, &pBlendStateCurrent);
		GetDeviceContext()->OMSetBlendState(pBlendStateCurrent, blendFactor, blendSampleMask);
	}
}
RenderTarget* DXDevice::GetCurrentRenderTarget()
{
	return renderTargetStack.back();
}
void DXDevice::PushRenderTarget(RenderTarget* rt)
{
	if(renderTargetStack.size() > 0)
	{
		GetDeviceContext()->Flush();
	}
	renderTargetStack.push_back(rt);
	GetDeviceContext()->OMSetRenderTargets(
			1,
			&rt->renderTargetView,
			rt->depthStencilView
			);
}
void DXDevice::PopRenderTarget()
{
	if(renderTargetStack.size() <= 1) return;
	GetDeviceContext()->Flush();
	renderTargetStack.pop_back();
	GetDeviceContext()->OMSetRenderTargets(
			1,
			&GetCurrentRenderTarget()->renderTargetView,
			GetCurrentRenderTarget()->depthStencilView
			);
}
void DXDevice::StartCommandChecking()
{
	if(bCommandCheckingStarted)
	{
		GetDeviceContext()->End(queryEvent);
		GetDeviceContext()->Begin(queryEvent);
	}
	else
	{
		bCommandCheckingStarted = true;
		GetDeviceContext()->Begin(queryEvent);
	}
}
void DXDevice::StopCommandChecking()
{
	if(bCommandCheckingStarted)
	{
		GetDeviceContext()->End(queryEvent);
		bCommandCheckingStarted = false;
	}
}
void DXDevice::FlushCommand()
{
	if(bCommandCheckingStarted)
	{
		GetDeviceContext()->Flush();
		GetDeviceContext()->End(queryEvent);
		while (S_FALSE == GetDeviceContext()->GetData(queryEvent, NULL /*&GPUfinished*/, 0 /*sizeof(GPUfinished)*/, 0))
		{
		}
		GetDeviceContext()->Begin(queryEvent);
	}
}